﻿using System;
using System.Threading.Tasks;
using Dpx.Models;
using Dpx.Services;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Ioc;

namespace Dpx.ViewModels {
    /// <summary>
    /// 同步页ViewModel。
    /// </summary>
    public class SyncPageViewModel : ViewModelBase {
        /******** 构造函数 ********/

        /// <summary>
        /// 使用OneDrive收藏存储的同步服务。
        /// </summary>
        internal ISyncService _oneDriveSyncService;

        /// <summary>
        /// 偏好存储。
        /// </summary>
        internal IPreferenceStorage _preferenceStorage;

        /// <summary>
        /// 同步页ViewModel。
        /// </summary>
        /// <param name="oneDriveFavoriteStorage">OneDrive收藏存储。</param>
        /// <param name="preferenceStorage">偏好存储。</param>
        [PreferredConstructor]
        public SyncPageViewModel(
            OneDriveFavoriteStorage oneDriveFavoriteStorage,
            IPreferenceStorage preferenceStorage) {
            _oneDriveSyncService = new SyncService(
                SimpleIoc.Default.GetInstance<IFavoriteStorage>(),
                oneDriveFavoriteStorage);
            _oneDriveSyncService.StatusChanged += (sender, args) =>
                OneDriveStatus = _oneDriveSyncService.Status;
            _oneDriveSyncService.RemoteFavoriteStorage.StatusChanged +=
                (sender, args) => OneDriveStatus =
                    _oneDriveSyncService.RemoteFavoriteStorage.Status;

            _preferenceStorage = preferenceStorage;
        }

        /// <summary>
        /// 同步页ViewModel。
        /// </summary>
        /// <remarks>
        /// 只用于单元测试。
        /// </remarks>
        internal SyncPageViewModel() {
        }

        /******** 绑定属性 ********/

        /// <summary>
        /// OneDrive已登录。
        /// </summary>
        public bool OneDriveSignedIn {
            get => _oneDriveSignedIn;
            set => Set(nameof(OneDriveSignedIn), ref _oneDriveSignedIn, value);
        }

        /// <summary>
        /// OneDrive已登录。
        /// </summary>
        private bool _oneDriveSignedIn;

        /// <summary>
        /// OneDrive正在载入。
        /// </summary>
        public bool OneDriveLoading {
            get => _oneDriveLoading;
            set => Set(nameof(OneDriveLoading), ref _oneDriveLoading, value);
        }

        /// <summary>
        /// OneDrive正在载入。
        /// </summary>
        private bool _oneDriveLoading;

        /// <summary>
        /// OneDrive状态。
        /// </summary>
        public string OneDriveStatus {
            get => _oneDriveStatus;
            set => Set(nameof(OneDriveStatus), ref _oneDriveStatus, value);
        }

        /// <summary>
        /// OneDrive状态。
        /// </summary>
        private string _oneDriveStatus;

        /// <summary>
        /// 上一次OneDrive同步时间。
        /// </summary>
        public DateTime LastOneDriveSyncTime {
            get =>
                _preferenceStorage.Get(LastOneDriveSyncTimeKey,
                    DateTime.MinValue);
            set {
                var oldValue = _preferenceStorage.Get(LastOneDriveSyncTimeKey,
                    DateTime.MinValue);
                if (oldValue == value) {
                    return;
                }

                _preferenceStorage.Set(LastOneDriveSyncTimeKey, value);
                RaisePropertyChanged(nameof(LastOneDriveSyncTime), oldValue,
                    value, false);
            }
        }

        /******** 绑定命令 ********/

        /// <summary>
        /// 页面显示命令。
        /// </summary>
        public RelayCommand PageAppearingCommand =>
            _pageAppearingCommand ?? (_pageAppearingCommand = new RelayCommand(
                async () => await PageAppearingCommandFunction()));

        /// <summary>
        /// 页面显示命令。
        /// </summary>
        private RelayCommand _pageAppearingCommand;

        internal async Task PageAppearingCommandFunction() {
            OneDriveLoading = true;
            OneDriveSignedIn = await _oneDriveSyncService.RemoteFavoriteStorage
                .IsSignedInAsync();
            OneDriveLoading = false;
        }

        /// <summary>
        /// OneDrive登录命令。
        /// </summary>
        public RelayCommand OneDriveSignInCommand =>
            _oneDriveSignInCommand ?? (_oneDriveSignInCommand =
                new RelayCommand(async () =>
                    await OneDriveSignInCommandFunction()));

        /// <summary>
        /// OneDrive登录命令。
        /// </summary>
        private RelayCommand _oneDriveSignInCommand;

        internal async Task OneDriveSignInCommandFunction() {
            OneDriveLoading = true;
            OneDriveSignedIn = await _oneDriveSyncService
                .RemoteFavoriteStorage.SignInAsync();
            OneDriveLoading = false;
        }

        /// <summary>
        /// OneDrive注销命令。
        /// </summary>
        public RelayCommand OneDriveSignOutCommand =>
            _oneDriveSignOutCommand ?? (_oneDriveSignOutCommand =
                new RelayCommand(async () =>
                    await OneDriveSignOutCommandFunction()));

        /// <summary>
        /// OneDrive注销命令。
        /// </summary>
        private RelayCommand _oneDriveSignOutCommand;

        internal async Task OneDriveSignOutCommandFunction() {
            OneDriveLoading = true;
            await _oneDriveSyncService.RemoteFavoriteStorage.SignOutAsync();
            OneDriveSignedIn = false;
            OneDriveLoading = false;
        }

        /// <summary>
        /// OneDrive同步命令。
        /// </summary>
        public RelayCommand OneDriveSyncCommand =>
            _oneDriveSyncCommand ?? (_oneDriveSyncCommand = new RelayCommand(
                async () => await OneDriveSyncCommandFunction()));

        /// <summary>
        /// OneDrive同步命令。
        /// </summary>
        private RelayCommand _oneDriveSyncCommand;

        internal async Task OneDriveSyncCommandFunction() {
            OneDriveLoading = true;

            var syncResult = await _oneDriveSyncService.SyncAsync();
            if (syncResult.Status == ServiceResultStatus.Ok) {
                LastOneDriveSyncTime = DateTime.Now;
            }

            OneDriveLoading = false;
        }

        /******** 私有变量 ********/

        /// <summary>
        /// OneDrive上次同步时间键。
        /// </summary>
        internal const string LastOneDriveSyncTimeKey =
            nameof(SyncPageViewModel) + "." + nameof(LastOneDriveSyncTime);
    }
}